using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;

using PickGold.Charting.Utilities;
using PickGold.Charting.Design;

namespace PickGold.Charting
{
	[SRDescription("DescriptionAttributeMapArea_MapArea"), DefaultProperty("ToolTip"), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	public class MapArea : ChartNamedElement, IChartMapArea
	{
		private string _attributes;
		private float[] _coordinates;
		private bool _isCustom;
		private Regex _mapAttributesRegex;
		private string _postBackValue;
		private MapAreaShape _shape;
		private string _toolTip;
		private string _url;

		public MapArea()
		{
			this._toolTip = string.Empty;
			this._url = string.Empty;
			this._attributes = string.Empty;
			this._postBackValue = string.Empty;
			this._isCustom = true;
			this._coordinates = new float[4];
		}

		public MapArea(string url, GraphicsPath path)
			: this(string.Empty, url, string.Empty, string.Empty, path, null)
		{
		}

		public MapArea(string url, RectangleF rect)
			: this(string.Empty, url, string.Empty, string.Empty, rect, null)
		{
		}

		public MapArea(MapAreaShape shape, string url, float[] coordinates)
			: this(shape, string.Empty, url, string.Empty, string.Empty, coordinates, null)
		{
		}

		public MapArea(string toolTip, string url, string attributes, string postBackValue, GraphicsPath path, object tag)
		{
			this._toolTip = string.Empty;
			this._url = string.Empty;
			this._attributes = string.Empty;
			this._postBackValue = string.Empty;
			this._isCustom = true;
			this._coordinates = new float[4];
			if (path.PointCount == 0)
			{
				throw new ArgumentException(SR.ExceptionImageMapPolygonShapeInvalid);
			}
			path.Flatten();
			PointF[] pathPoints = path.PathPoints;
			float[] coordinates = new float[pathPoints.Length * 2];
			int num = 0;
			foreach (PointF tf in pathPoints)
			{
				coordinates[num++] = tf.X;
				coordinates[num++] = tf.Y;
			}
			this.Initialize(MapAreaShape.Polygon, toolTip, url, attributes, postBackValue, coordinates, tag);
		}

		public MapArea(string toolTip, string url, string attributes, string postBackValue, RectangleF rect, object tag)
		{
			this._toolTip = string.Empty;
			this._url = string.Empty;
			this._attributes = string.Empty;
			this._postBackValue = string.Empty;
			this._isCustom = true;
			this._coordinates = new float[4];
			float[] coordinates = new float[] { rect.X, rect.Y, rect.Right, rect.Bottom };
			this.Initialize(MapAreaShape.Rectangle, toolTip, url, attributes, postBackValue, coordinates, tag);
		}

		public MapArea(MapAreaShape shape, string toolTip, string url, string attributes, string postBackValue, float[] coordinates, object tag)
		{
			this._toolTip = string.Empty;
			this._url = string.Empty;
			this._attributes = string.Empty;
			this._postBackValue = string.Empty;
			this._isCustom = true;
			this._coordinates = new float[4];
			this.Initialize(shape, toolTip, url, attributes, postBackValue, coordinates, tag);
		}

		private static string EncodeValue(Chart chart, string name, string value)
		{
			if (!chart.IsMapAreaAttributesEncoded || (!IsJavaScript(value) && !name.Trim().StartsWith("on", StringComparison.OrdinalIgnoreCase)))
			{
				return value;
			}
			return HttpUtility.UrlEncode(value);
		}

		private string GetCoordinates(ChartGraphics graph)
		{
			float[] numArray = new float[this.Coordinates.Length];
			if (this.Shape == MapAreaShape.Circle)
			{
				PointF absolutePoint = graph.GetAbsolutePoint(new PointF(this.Coordinates[0], this.Coordinates[1]));
				numArray[0] = absolutePoint.X;
				numArray[1] = absolutePoint.Y;
				absolutePoint = graph.GetAbsolutePoint(new PointF(this.Coordinates[2], this.Coordinates[1]));
				numArray[2] = absolutePoint.X;
			}
			else if (this.Shape == MapAreaShape.Rectangle)
			{
				PointF tf2 = graph.GetAbsolutePoint(new PointF(this.Coordinates[0], this.Coordinates[1]));
				numArray[0] = tf2.X;
				numArray[1] = tf2.Y;
				tf2 = graph.GetAbsolutePoint(new PointF(this.Coordinates[2], this.Coordinates[3]));
				numArray[2] = tf2.X;
				numArray[3] = tf2.Y;
				if (((int)Math.Round((double)numArray[0])) == ((int)Math.Round((double)numArray[2])))
				{
					numArray[2] = ((float)Math.Round((double)numArray[2])) + 1f;
				}
				if (((int)Math.Round((double)numArray[1])) == ((int)Math.Round((double)numArray[3])))
				{
					numArray[3] = ((float)Math.Round((double)numArray[3])) + 1f;
				}
			}
			else
			{
				PointF empty = (PointF)Point.Empty;
				PointF point = (PointF)Point.Empty;
				for (int i = 0; i < (this.Coordinates.Length - 1); i += 2)
				{
					point.X = this.Coordinates[i];
					point.Y = this.Coordinates[i + 1];
					empty = graph.GetAbsolutePoint(point);
					numArray[i] = empty.X;
					numArray[i + 1] = empty.Y;
				}
			}
			StringBuilder builder = new StringBuilder();
			bool flag = true;
			foreach (float num2 in numArray)
			{
				if (!flag)
				{
					builder.Append(",");
				}
				flag = false;
				builder.Append((int)Math.Round((double)num2));
			}
			return builder.ToString();
		}

		private string GetShapeName()
		{
			if (this._shape == MapAreaShape.Circle)
			{
				return "circle";
			}
			if (this._shape == MapAreaShape.Rectangle)
			{
				return "rect";
			}
			if (this._shape == MapAreaShape.Polygon)
			{
				return "poly";
			}
			return string.Empty;
		}

		private void Initialize(MapAreaShape shape, string toolTip, string url, string attributes, string postBackValue, float[] coordinates, object tag)
		{
			if ((shape == MapAreaShape.Circle) && (coordinates.Length != 3))
			{
				throw new InvalidOperationException(SR.ExceptionImageMapCircleShapeInvalid);
			}
			if ((shape == MapAreaShape.Rectangle) && (coordinates.Length != 4))
			{
				throw new InvalidOperationException(SR.ExceptionImageMapRectangleShapeInvalid);
			}
			if ((shape == MapAreaShape.Polygon) && ((((float)coordinates.Length) % 2f) != 0f))
			{
				throw new InvalidOperationException(SR.ExceptionImageMapPolygonShapeInvalid);
			}
			this._toolTip = toolTip;
			this._url = url;
			this._attributes = attributes;
			this._shape = shape;
			this._coordinates = new float[coordinates.Length];
			this._postBackValue = postBackValue;
			base.Tag = tag;
			coordinates.CopyTo(this._coordinates, 0);
		}

		private static bool IsJavaScript(string value)
		{
			return value.Trim().Replace("\r", string.Empty).Replace("\n", string.Empty).StartsWith("javascript:", StringComparison.OrdinalIgnoreCase);
		}

		internal void RenderTag(HtmlTextWriter writer, Chart chart)
		{
			StringBuilder builder = new StringBuilder();
			writer.WriteLine();
			writer.AddAttribute(HtmlTextWriterAttribute.Shape, this.GetShapeName(), false);
			writer.AddAttribute(HtmlTextWriterAttribute.Coords, this.GetCoordinates(chart.ChartPicture.ChartGraph));
			if (!string.IsNullOrEmpty(this.ToolTip))
			{
				builder.Append("title,");
				writer.AddAttribute(HtmlTextWriterAttribute.Title, EncodeValue(chart, "title", this.ToolTip));
			}
			bool flag = false;
			if (!string.IsNullOrEmpty(this.Url))
			{
				builder.Append("href,");
				string str = chart.ResolveClientUrl(this.Url);
				writer.AddAttribute(HtmlTextWriterAttribute.Href, EncodeValue(chart, "href", str));
			}
			else if (!string.IsNullOrEmpty(this.PostBackValue) && (chart.Page != null))
			{
				flag = true;
				builder.Append("href,");
				writer.AddAttribute(HtmlTextWriterAttribute.Href, chart.Page.ClientScript.GetPostBackClientHyperlink(chart, this.PostBackValue));
			}
			if ((!flag && !string.IsNullOrEmpty(this.PostBackValue)) && (chart.Page != null))
			{
				builder.Append("onclick,");
				writer.AddAttribute(HtmlTextWriterAttribute.Onclick, chart.Page.ClientScript.GetPostBackEventReference(chart, this.PostBackValue));
			}
			if (!string.IsNullOrEmpty(this._attributes))
			{
				string str2 = builder.ToString();
				if (this._mapAttributesRegex == null)
				{
					this._mapAttributesRegex = new Regex("\\s?(?<name>(\\w+))\\s?=\\s?\"(?<value>[^\"]+)\"\\s?", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
				}
				foreach (Match match in this._mapAttributesRegex.Matches(this._attributes))
				{
					Group group = match.Groups["name"];
					Group group2 = match.Groups["value"];
					for (int i = 0; (i < group.Captures.Count) || (i < group2.Captures.Count); i++)
					{
						string name = group.Captures[i].Value.ToLowerInvariant();
						string str4 = group2.Captures[i].Value;
						if (!str2.Contains(name + ","))
						{
							if ("src,href,longdesc,background,".Contains(name + ",") && !IsJavaScript(str4))
							{
								str4 = chart.ResolveClientUrl(str4);
							}
							else
							{
								str4 = HttpUtility.HtmlAttributeEncode(str4);
							}
							str4 = EncodeValue(chart, name, str4);
							writer.AddAttribute(name, str4, false);
						}
					}
				}
			}
			if (this._attributes.IndexOf(" alt=", StringComparison.OrdinalIgnoreCase) == -1)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Alt, "");
			}
			writer.RenderBeginTag(HtmlTextWriterTag.Area);
			writer.RenderEndTag();
		}

		[DefaultValue(""), Bindable(true), SRDescription("DescriptionAttributeMapArea_Coordinates"), TypeConverter(typeof(MapAreaCoordinatesConverter)), SRCategory("CategoryAttributeShape"), PersistenceMode(PersistenceMode.Attribute)]
		public float[] Coordinates
		{
			get
			{
				return this._coordinates;
			}
			set
			{
				this._coordinates = value;
			}
		}

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), SRDescription("DescriptionAttributeMapArea_Custom"), DefaultValue(""), Browsable(false), SerializationVisibility(SerializationVisibility.Hidden)]
		public bool IsCustom
		{
			get
			{
				return this._isCustom;
			}
			internal set
			{
				this._isCustom = value;
			}
		}

		[DefaultValue(""), SRDescription("DescriptionAttributeMapAreaAttributes"), SRCategory("CategoryAttributeMapArea"), PersistenceMode(PersistenceMode.Attribute), Bindable(true)]
		public string MapAreaAttributes
		{
			get
			{
				return this._attributes;
			}
			set
			{
				this._attributes = value;
			}
		}

		[Browsable(false), SerializationVisibility(SerializationVisibility.Hidden), SRDescription("DescriptionAttributeMapArea_Name"), DefaultValue("Map Area"), SRCategory("CategoryAttributeData"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public override string Name
		{
			get
			{
				return base.Name;
			}
			set
			{
				base.Name = value;
			}
		}

		[SRCategory("CategoryAttributeMapArea"), SRDescription("DescriptionAttributePostBackValue"), DefaultValue("")]
		public string PostBackValue
		{
			get
			{
				return this._postBackValue;
			}
			set
			{
				this._postBackValue = value;
			}
		}

		[DefaultValue(typeof(MapAreaShape), "Rectangle"), PersistenceMode(PersistenceMode.Attribute), Bindable(true), SRDescription("DescriptionAttributeMapArea_Shape"), SRCategory("CategoryAttributeShape")]
		public MapAreaShape Shape
		{
			get
			{
				return this._shape;
			}
			set
			{
				this._shape = value;
			}
		}

		[SRCategory("CategoryAttributeMapArea"), DefaultValue(""), PersistenceMode(PersistenceMode.Attribute), Bindable(true), SRDescription("DescriptionAttributeToolTip")]
		public string ToolTip
		{
			get
			{
				return this._toolTip;
			}
			set
			{
				this._toolTip = value;
			}
		}

		[Editor(typeof(UrlValueEditor), typeof(UITypeEditor)), SRCategory("CategoryAttributeMapArea"), Bindable(true), SRDescription("DescriptionAttributeUrl"), DefaultValue(""), PersistenceMode(PersistenceMode.Attribute)]
		public string Url
		{
			get
			{
				return this._url;
			}
			set
			{
				this._url = value;
			}
		}
	}
}

